home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp48_1
/
dft.stu
< prev
next >
Wrap
Text File
|
1995-03-23
|
9KB
|
273 lines
Article 2502 of comp.sys.handhelds:
Path: en.ecn.purdue.edu!noose.ecn.purdue.edu!samsung!uakari.primate.wisc.edu!sdd.hp.com!usc!apple!agate!shelby!portia.stanford.edu!elaine3.stanford.edu!mcgrant
From: mcgrant@elaine3.stanford.edu (Michael Grant)
Newsgroups: comp.sys.handhelds
Subject: A convenient little set of DFT functions, PART 1
Summary: My homework is one heck of a lot easier now
Keywords: DFT FFT DHT FHT CIA NSA ASPCA
Message-ID: <1990Nov21.191129.5321@portia.Stanford.EDU>
Date: 21 Nov 90 19:11:29 GMT
Sender: mcgrant@portia.stanford.edu
Followup-To: comp.sys.handhelds
Organization: Stanford University - AIR
Lines: 256
Many of you asked for my programs concerning 1) matrix resolvents,
and 2) DFT's and convolutions of discrete functions. The former
shall come at a future time, but, for now, here are the DFT
programs.
All of these functions operate on column vectors. Originally,
they worked on lists, but there are so many functions that
can be performed on the elements of an array that I just HAD
to convert them. SO, they don't follow conventional notation
like they used to, but they are now part of a much more
powerful repertoire of functions.
The following programs are a set that I have compiled for my
OWN benefit to perform some simple DFT analysis for academic
functions. They are by no means awesome; they only handle one
dimension, and they aren't terribly fast. BUT, they sure have
saved time on homework and exams...
While I THINK they are bug-free, I had to type them in by hand,
so who knows. Of course, I don't musspelll tu muche when I type,
so perhaps these will be OK. In any case, I would appreciate it
if you notify me of any corrections that need to be made
(at mcgrant@portia.stanford.edu).
NOTE: I will post an un-commented set of these next, so that
you will have less editing to do. Note that I have a 28S, so
these programs may have to be tweaked...
---
I recommend this order in your directory:
{ DFT IDFT DHT IDHT CCNV LCNV PROD MP->C C->MP
PAD2 RPAD ZPAD SAMP AR01 AR02 PRCSN } ORDER
'DFT' -- performs a Discrete Fourier Transform
on the given input vector.
INPUT: 1: a column vector L
OUTPUT: 1: DFT(L)
REQUIRES: DHT
COMMENTS: This program uses the Discrete Hartley Transform.
The DHT is a lot faster than the DFT, and the
time required to extract the DFT from the DHT is
minimal in comparison. Of course, for real speed,
perhaps someday I will write an FHT/FFT!
<< DHT DUP ARRY-> SZ
<< 2 SZ LIST-> DROP 1 -
FOR I I ROLL
NEXT SZ ->ARRY
>> DUP2 - (0,1) * - +
IF DUP IM CNRM NOT
THEN RE
END .5 *
>>
'IDFT' -- performs an Inverse Discrete Fourier Transform
INPUT: 1: a column vector L
OUTPUT: 1: IDFT(L)
REQUIRES: DFT
COMMENTS: Nothing more than INV(N)*CONJ(DFT(CONJ(L)).
<< CONJ DFT CONJ DUP SIZE LIST-> DROP / >>
'DHT' -- performs a Discrete Hartley Transform
INPUT: 1: a column vector L
OUTPUT: 1: DHT(L)
REQUIRES: PRCSN
COMMENTS: The Discrete Hartley Transform uses cas(theta)=
cos(theta)+sin(theta) as its kernel. Some people
will notice that this can be calculated as sqrt(2)*
sin(theta+pi/4), but for some reason this calculation
just wasn't quite as accurate as sin+cos; besides,
the speed savings is not all that great.
The PRCSN variable tells the DHT to round the answers
to PRCSN digits. I do this because 4.0000000001 takes
up the whole screen, tho' I know it's 4!
Notice that ~pi~ is the pi key .
<< DUP SIZE LIST-> DROP RCLF -> L N F
<< RAD PRCSN FIX L ~pi~ ~pi~ + -> S
<< 0 N 1 -
FOR J J N / S * DUP SIN SWAP COS + J 1 + SWAP PUT
NEXT
>> -> C
<< L 0 N 1 -
FOR J 0 0 N 1 -
FOR K J * N MOD 1 + GET 'L' K 1 + GET * +
NEXT RND J 1 + SWAP PUT
NEXT
>> F STOF
>>
>>
'IDHT' -- performs an Inverse Discrete Hartley Transform.
INPUT: 1: a column vector L
OUTPUT: 1: IDHT(L)
REQUIRES: DHT
COMMENTS: DHT is symmetric, so this is easy (N^-1*DHT(L)).
<< DHT DUP SIZE LIST-> DROP / >>
'SAMP' -- generates an array by sampling a function.
INPUT: 2: a self-contained function F
1: the number of samples to take
OUTPUT: [ F(0) F(1) F(2) ... F(N-1) ]
COMMENTS: Sorry this isn't more complex guys and gals, but
it works fine for me.
<< -> F N
<< 0 N 1 -
FOR J J F EVAL
NEXT { N } ->ARRY
>>
>>
'ARO2' -- performs a binary operation on the elements of
two vectors (thereby combining them).
INPUT: 3: column vector L1 (size S1)
2: column vector L2 (size S2)
1: a self-contained binary function F
OUTPUT: [ F(L1(1),L2(1)) F(L1(2),L2(2)) ...
F(L1(min(S1,S2)),L2(min(S1,S2))) ]
COMMENTS: Notice that, if the two lists are of different
sizes, that AR02 truncates (in effect) the
longer one to match the size of the shorter one.
<< -> L1 L2 PR
<< L1 SIZE LIST-> DROP L2 SIZE LIST-> DROP MIN -> N
<< L1 { N } RDM 1 N
FOR J 'L1' J GET 'L2' J GET PR EVAL J SWAP PUT
NEXT
>>
>>
>>
'PROD' -- Performs an element-by-element multiplication.
INPUT: 2: column vector L1 (size S1)
1: column vector L2 (size S2)
OUTPUT: [ L1(1)*L2(1) L1(2)*L2(2) ... L1(min(S1,S2))*L2(min(S1,S2)) ]
REQUIRES: ARO2
COMMENTS: See ARO2. This function is useful because convolution
in one domain is equivalent to multiplication in the
other domain...but this is not QUITE true for Hartley...
<< << * >> ARO2 >>
'AR01' -- Performs a function on each element of the vector.
INPUT: 2: column vector L (size N)
1: self-contained function F
OUTPUT: 1: [ F(1) F(2) ... F(N) ]
COMMENTS: well, I just use this for C->MP and MP->C below.
<< -> L PR
<< L SIZE LIST-> DROP -> N
<< L 1 N
FOR J 'L' J GET PR EVAL J SWAP PUT
NEXT
>>
>>
>>
'C->MP' -- converts a vector from complex to mag/phase.
INPUT: 1: column vector L (size N)
OUTPUT: 1: [ R->P(L(1)) R->P(L(2)) ... R->P(L(N)) ]
REQUIRES: AR01
COMMENTS: Convenient when you just want the magnitude
of your DFT (just do a C->MP RE)!
<< (1,0) * << R->P >> ARO1 >>
'MP->C' -- converts a vector from mag/phase to complex.
INPUT: 1: column vector L (size N)
OUTPUT: 1: [ P->R(L(1)) P->R(L(2)) ... P->R(L(N)) ]
REQUIRES: AR01
COMMENTS: When you're too short-sighted to remember to
save the original answer to the DFT...
<< (1,0) * << P->R >> ARO1 >>
'CCNV' -- performs the circular convolution of two vectors
INPUT: 2: column vector L1 (size N)
1: column vector L2 (size N)
OUTPUT: 1: L1 C* L2 (size N)
COMMENTS: This program will generate an error if the two lists
are of different sizes. So, use ZPAD, PAD2, or
RPAD to adjust the sizes of your vectors.
<< DUP SIZE LIST-> DROP -> L1 L2 N
<< IF N L1 SIZE LIST-> DROP <>
THEN [ 1 ] TRN
ELSE L1 1 N
FOR J 0 1 N
FOR K 'L1' K GET 'L2' J K - N MOD 1 + GET * +
NEXT J SWAP PUT
NEXT
END
>>
>>
'LCNV' -- performs the linear convolution of two vectors
INPUT: 2: column vector L1 (size N1)
1: column vector L2 (size N2)
OUTPUT: 1: L1 * L2 (size N1+N2-1)
REQUIRES: PAD2 CCNV
COMMENTS: Gee, the REQUIRES line is longer than the program!
<< PAD2 CCNV >>
'PAD2' -- pads two vectors so L1 C* L2 <==> L1 * L2
INPUT: 2: column vector L1 (size N1)
1: column vector L2 (size N2)
OUTPUT: 2: column vector L1 (size N1+N2-1)
1: column vector L2 (size N1+N2-1)
COMMENTS: This program is essential to the proper operation of
LCNV, because circular convolution must 'see' enough
padded zeros so that no circular overlap occurs.
<< DUP2 SIZE LIST-> DROP SWAP SIZE LIST-> DROP + 1 - 1 ->LIST -> S
<< S RDM SWAP S RDM SWAP >>
>>
'ZPAD' -- adds as many zeros as is necessary to extend the
input vector to at least N elements
INPUT: 2: column vector L (size M)
1: the desired new vector size N
OUTPUT: IF N>M, 1: RDM(L,N)
IF N<M, 2: L
COMMENTS: Not much to this.
<< -> L N
<< L
IF L SIZE LIST-> DROP N <
THEN { N } RDM
END
>>
>>
'RPAD' -- replicate the vector to hit N vectors.
INPUT: 2: column vector L (size M)
1: the desired new vector size N
OUTPUT: IF N>M: [ L(1) L(2) ... L(M) L(1) .. L(M) ... ] (size N)
IF N<M: L
COMMENTS: This is useful when circularly convolving two functions
one's period is a multiple of the other's. Otherwise,
I can't think of any mathematically safe use for this.
<< -> L N
<< L SIZE LIST-> DROP -> M
<< L
IF M N <
THEN { N } RDM M 1 + N
FOR J 'L' J M MOD
IF DUP NOT
THEN DROP M
END GET J SWAP PUT
NEXT
END
>>
>>
>>
'PRCSN' -- # of digits to RND to in DHT
COMMENTS: I recommend a fairly large number, though my
experience is that the DHT is accurate to about
10 digits (as far as roundoff error goes).
10
---
Michael C. Grant "God does not play dice." Einstein
Information Systems Lab "Geez, He'd win a lot if he did,
mcgrant@portia.stanford.edu though..." Mike